package com.onpositive.knowledge.model.values;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import com.onpositive.knowledge.model.value.audits.AbstractAuditResult;
import com.onpositive.semantic.model.api.property.IProperty;

public class ReplacementProposals extends AbstractAuditResult {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2252305491129784654L;
	
	private HashMap<Object,List<Proposal>> proposalsMap = new HashMap<Object, List<Proposal>>() ;
	private int validityBarrier = Integer.MAX_VALUE ;
	
	
	public ReplacementProposals(IProperty prop) {
		super(prop);
	}
	
	static public class Proposal implements Serializable{
		
		/**
		 * 
		 */
		private static final long serialVersionUID = 536045053587030687L;

		private static int TRIVIAL_WEIGHT_VALUE = Integer.MIN_VALUE ;
		
		public Object value ;		
		public int weight ;
		
		public Proposal()
		{
			this.weight = TRIVIAL_WEIGHT_VALUE ;
		}
		public boolean isNonTrivial(){ return this.weight != TRIVIAL_WEIGHT_VALUE ; }
		
		public Proposal(Object vlaue, int weight) {
			super();
			this.value = vlaue;
			this.weight = weight;
		}

		public Object getVlaue() {
			return value;
		}

		public int getWeight() {
			return weight;
		}
		
		public String toString(){
			return value + ":" + weight ;
		}
	}
	static private class ProposalComparator implements Comparator<Proposal>{

		public int compare(Proposal arg0, Proposal arg1) {
			
			return arg0.getWeight() - arg1.getWeight() ;
		}
		
	}
	private static ProposalComparator pComp = new ProposalComparator() ;
	
	public List<Proposal> getProposals( Object obj )
	{
		List<Proposal> col = this.proposalsMap.get( obj ) ;
		Collections.sort( col, pComp) ;
//		
//		ArrayList<Proposal> result = new ArrayList<Proposal>() ;
//		for( Proposal p : col )
//			result.add( p ) ;
		return col ;
	}
	
	public Proposal getBestProposal( Object obj )
	{		
		List<Proposal> col = this.proposalsMap.get( obj ) ;
		if( col == null )
			return null ;
		
		return chooseBestProposalFronList(col);
	}


	
	
	public void takeProposal( Object subj, Object proposal, int weight )
	{
		if( subj == null || proposal == null )
			return ;
		
		setLooksApplyable( true ) ;
		List<Proposal> col = this.proposalsMap.get( subj ) ;
		if( col == null )
		{
			col = createCollection() ;
			this.proposalsMap.put( subj, col ) ;
		}
		
		col.add( new Proposal(proposal, weight) ) ;
	}
	
	public boolean isEmpty(){
		return proposalsMap.isEmpty() ;
	}
	
	public void takeProposal( Object subj, Proposal proposal )
	{
		if( subj == null || proposal == null )
			return ;
		
		setLooksApplyable( true ) ;
		List<Proposal> col = this.proposalsMap.get( subj ) ;
		if( col == null )
		{
			col = createCollection() ;
			this.proposalsMap.put( subj, col ) ;
		}
		
		col.add( proposal ) ;
	}
	
//	public void takeProposals( Object subj, Collection<Object> proposals, Collection<Integer> weights )
//	{
//		if( subj == null || proposals == null || proposals.size() == 0 )
//			return ;
//
//		setLooksApplyable( true ) ;
//		Collection<Object> col = this.proposalsMap.get( subj ) ;
//		if( col == null )
//			this.proposalsMap.put( subj, proposals ) ;
//		else
//			col.addAll(proposals) ;
//	}
	
	
	protected List<Proposal> createCollection()
	{
		return new ArrayList<Proposal>() ;
	}

	protected static Proposal chooseBestProposalFronList( Collection<Proposal> col) {
		if (col==null){
			return null;
		}
		Proposal result = col.iterator().next() ;
		
		for( Proposal p : col )
			result =  p.getWeight() > result.getWeight() ? p : result ;
				
		return result ;
	}
	
	public static class BestProposalInfo implements Serializable{
		/**
		 * 
		 */
		private static final long serialVersionUID = -4519954229140510454L;
		Object object;
		Object value;
		int weight;
	}
	
	public List<BestProposalInfo> getBestProposalsInfo(){
		ArrayList<BestProposalInfo>d=new ArrayList<ReplacementProposals.BestProposalInfo>();
		for (Object o:proposalsMap.keySet()){
			List<Proposal> list = proposalsMap.get(o);
			if (list!=null){
				BestProposalInfo m=new BestProposalInfo();
				m.object=o;
				Proposal chooseBestProposalFronList = chooseBestProposalFronList(list);
				m.value=chooseBestProposalFronList.value;
				m.weight=chooseBestProposalFronList.weight;
				d.add(m);
			}
		}
		return d;		
	}

	public int getValidityBarrier() {
		return validityBarrier;
	}

	public void setValidityBarrier(int validityBarrier) {
		this.validityBarrier = validityBarrier;
	}
}
